<!-- 
    右侧：虚拟列表展示日志
    底部：暂停 / 恢复 / 清空 / 导出按钮
    顶部：关键字过滤、日志级别选择
    左侧：实时概览面板，统计 info/warn/error 数量（自动更新）
-->
<template>
	<div class="test-page">
		<div class="left-sidebar">
			<div class="sidebar-title">日志列表</div>
			<div class="subtitle">日志分类统计</div>
			<div
				class="sidebar-row"
				v-for="(box, index) in logTypeCount"
				:key="index"
			>
				<div class="label">
					<span :class="box.key">{{ box.name }}:</span>
				</div>
				<div class="content">
					<span>{{ box.value }}</span>
				</div>
			</div>

			<div class="sidebar-row">
				<div class="label">
					<span>模拟运行:</span>
				</div>
				<div class="content">
					<span class="warn" v-if="isRead">读取中</span>
					<span class="error" v-else>停止读取</span>
				</div>
			</div>

			<div class="y-flex-wrap">
				<div class="page-btn" v-if="isRead" @click="SimulateRun('s')">
					暂停接收
				</div>
				<div class="page-btn" v-else @click="SimulateRun('r')">
					接收日志
				</div>
			</div>

			<div class="y-flex-wrap">
				<div class="page-btn" @click="TotalListClear">清空日志</div>
				<div class="page-btn" @click="ExportLogsFun1">
					导出5s前到现在的日志
				</div>
			</div>
		</div>
		<div class="page-main">
			<div class="page-top">
				<div class="y-flex-wrap">
					<div
						class="page-btn"
						:class="{ active: logType === 'info' }"
						@click="BtnCheckType('info')"
					>
						<span>查看</span>
						<span class="info">info</span>
					</div>
					<div
						class="page-btn"
						:class="{ active: logType === 'warn' }"
						@click="BtnCheckType('warn')"
					>
						<span>查看</span>
						<span class="warn">warn</span>
					</div>
					<div
						class="page-btn"
						:class="{ active: logType === 'error' }"
						@click="BtnCheckType('error')"
					>
						<span>查看</span>
						<span class="error">error</span>
					</div>
				</div>

				<!-- 搜索 -->
				<div class="search">
					<formInput
						v-model:modelValue="searchValue"
						label="搜索数据"
						placeholder="请输入搜索内容"
					/>
				</div>
			</div>

			<!-- 日志列表容器 -->
			<div class="list-container">
				<VirtualList
					ref="virtualListRef"
					:containerHeight="700"
					:itemHeight="100"
					:chunkSize="2000"
					:list="showList"
				>
					<template #default="{ item }">
						<div class="list-box">
							<p class="subtitle">
								<span>日志ID:</span>
								<span>{{ item.id }}</span>
							</p>
							<p class="txt">
								<span>内容:</span>
								<span :class="item.level">{{
									item.content
								}}</span>
							</p>
							<p class="txt">
								<span>日期时间:</span>
								<span>{{ item.timestamp }}</span>
							</p>
						</div>
					</template>
				</VirtualList>
			</div>

			<div class="page-bottom">
				<div class="y-flex-wrap">
					<div class="page-btn" @click="BtnScrollTop">
						滚动到列表顶部
					</div>
					<div class="page-btn" @click="BtnScrollBottom">
						滚动到列表底部
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
// #导出vue方法
import { computed, onMounted, ref } from "vue";

// 虚拟列表组件
import VirtualList from "../components/virtual-list/index2.vue";

// 输入框
import formInput from "../components/wen-dynamic-form/form-input.vue";

// -------------------------------------------------------------------
// 日志列表
const virtualListRef = ref(null);
// 当前查看的类型
const logType = ref(null);

const totalList = ref([]);

// 搜索关键词
const searchValue = ref(null);

// 计算属性
const showList = computed(() => {
	if (!logType.value && !searchValue.value) {
		return totalList.value;
	} else {
		// 有过滤条件或搜索关键词
		return totalList.value.filter((box) => {
			// 判断条件
			let isArr = [];
			if (logType.value) {
				isArr.push(logType.value === box.level);
			}

			if (searchValue.value) {
				isArr.push(box.content.indexOf(searchValue.value) !== -1);
			}

			// 数组内所有条件都满足则显示
			const allTrue = isArr.every(Boolean);

			return allTrue;
		});
	}
});

// 日志分类数量统计
const logTypeCount = computed(() => {
	const objv = {
		info: 0,
		warn: 0,
		error: 0,
	};

	totalList.value.forEach((box) => {
		if (box.level) {
			objv[box.level]++;
		}
	});

	let res = [];
	for (let k in objv) {
		res.push({
			name: "日志-" + k,
			key: k,
			value: objv[k],
		});
	}

	res.unshift({
		name: "总日志数",
		key: "all",
		value: totalList.value.length,
	});

	return res;
});

onMounted(() => {
	totalList.value = [];
	/* for (let i = 0; i < 100000; i++) {
		totalList.value.push({
			id: i,
			timestamp: 123213123123,
			level: "warn",
			content: "123123123123",
		});
	} */
});

// 滚动到列表顶部
const BtnScrollTop = () => {
	virtualListRef.value.scrollToTop();
};

// 滚动到列表底部
const BtnScrollBottom = () => {
	virtualListRef.value.scrollToBottom();
};

// 查看指定类型
const BtnCheckType = (type) => {
	if (type === logType.value) {
		logType.value = null;
	} else {
		logType.value = type;
	}
};

// -------------------------------------------------------------------
// 模拟数据写入
const isRead = ref(false);
const readTimer = ref(null);

// 模拟运行开关
const SimulateRun = (type = "r") => {
	if (type === "r") {
		SimulateReading();
	}

	if (type === "s") {
		clearInterval(readTimer.value);
		isRead.value = false;
	}
};

// 模拟读取程序
const SimulateReading = () => {
	isRead.value = true;
	clearInterval(readTimer.value);
	readTimer.value = setInterval(() => {
		// 每秒增加50条数据
		for (let i = 0; i < 50; i++) {
			TotalListAddData();
		}

		if (totalList.value.length > 20000) {
			console.log("数量达到上限，停止运行");
			clearInterval(readTimer.value);
		}
	}, 1000);
};

// 往列表内写入假数据
const TotalListAddData = () => {
	const levels = ["info", "warn", "error"];
	const txts = ["水路控制板", "翻炒板", "功率板"];
	const randomNum = Math.floor(Math.random() * 3);
	const randomNum2 = Math.floor(Math.random() * 3);
	const index = totalList.value.length;
	const box = {
		id: index,
		timestamp: new Date().getTime(),
		level: levels[randomNum],
		content: txts[randomNum2],
	};

	totalList.value.push(box);
};

// 清空日志
const TotalListClear = () => {
	totalList.value = [];
};

// -------------------------------------------------------------------
// 导出5s前到现在的日志
const ExportLogsFun1 = () => {
	if (showList.value.length === 0) {
		return;
	}

	let resArrs = [];
	const lastTime = new Date().getTime() - 5000;
	resArrs = showList.value.filter((box) => {
		if (box.timestamp > lastTime) {
			return true;
		}
	});

	ExportJSON(resArrs, "测试导出json.json");
};

// -------------------------------------------------------------------
// 导出JSON数据
const ExportJSON = (data, filename = "data.json") => {
	console.log("导出JSON数据");
	// 1.对传入的数组进行序列化
	const jsonStr = JSON.stringify(data, null, 2);

	// 2.创建 Blob
	const blob = new Blob([jsonStr], { type: "application/json" });

	// 3.创建下载链接
	const url = URL.createObjectURL(blob);
	const a = document.createElement("a");

	a.href = url;
	// 文件名
	a.download = filename;

	// 4.触发下载
	document.body.appendChild(a);
	a.click();

	// 5.清理
	document.body.removeChild(a);
	URL.revokeObjectURL(url);
};
</script>

<style scoped lang="less">
.test-page {
	width: 100vw;
	height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: #000000;

	color: #ffffff;
	font-size: 20px;

	.info {
		color: #c2c2c2;
	}

	.warn {
		color: rgba(24, 1147, 202, 1);
	}

	.error {
		color: rgba(181, 24, 67, 1);
	}

	.left-sidebar {
		width: 30%;
		height: 100%;
		padding: 50px 40px;
		background-color: rgba(28, 28, 30, 1);

		.sidebar-title {
			font-size: 30px;
			margin-bottom: 10px;
		}

		.subtitle {
			margin-bottom: 10px;
			font-size: 24px;
		}

		.sidebar-row {
			margin-bottom: 10px;
			display: flex;
			font-size: 20px;

			.label {
				width: 40%;
				margin-right: 10px;
			}

			.content {
				flex: 1;
			}
		}
	}

	.page-main {
		flex: 1;
		height: 100%;
		display: flex;
		flex-direction: column;

		.page-top {
			width: 100%;
			height: 220px;
			padding: 0 12px;
		}

		/* 列表容器 */
		.list-container {
			width: 100%;
			height: 700px;
			border: 2px solid #ffffff;
			border-radius: 10px;

			.list-box {
				margin: 0 30px;
				width: calc(100% - 30px);
				height: 90%;
				padding: 0 24px;
				background-color: rgba(28, 28, 30, 1);
				border-radius: 16px;
			}

			.subtitle {
				font-size: 24px;
			}

			.txt {
				font-size: 20px;
				color: #c2c2c2;
			}
		}

		.page-bottom {
			flex: 1;
			width: 100%;
			padding: 12px;
		}

		.search {
			background-color: #bdbdbd;
			padding: 10px;
			border-radius: 12px;
		}
	}

	.page-btn {
		margin: 6px;
		height: 60px;
		border-radius: 12px;
		background-color: rgba(40, 40, 40, 0.7);
		padding: 0 20px;
		font-size: 20px;
		color: #ffffff;
		line-height: 60px;

		&:active {
			background-color: #ff7b00;
		}

		&.active {
			background-color: #ff7b00;
		}
	}

	.y-flex-wrap {
		display: flex;
		flex-wrap: wrap;
	}
}
</style>
